<template>
  <div class="container">
    <header>
      <button class="home-button" @click="goToHome">
        <i class="fas fa-home"></i> 返回主页面
      </button>
      <h1>甲骨文单字检索工具</h1>
      <p class="subtitle">上传甲骨文单字图片，检索匹配的甲骨片并查看详细信息。点击高亮字形可查看其在甲骨片上的位置。</p>
    </header>
    
    <div class="upload-section">
      <div class="upload-area" 
           @click="triggerFileInput"
           @dragover.prevent="handleDragOver"
           @dragleave="handleDragLeave"
           @drop.prevent="handleDrop"
           :style="uploadAreaStyle">
        <i class="fas fa-cloud-upload-alt upload-icon"></i>
        <p class="upload-text">点击或拖拽上传甲骨文字符图片</p>
        <p class="upload-hint">支持JPG、PNG格式，建议使用清晰的单字图片</p>
        <input type="file" 
               ref="fileInput"
               class="file-input" 
               accept="image/*"
               @change="handleFileChange">
      </div>
      
      <div class="preview-container">
        <p class="preview-title">图片预览</p>
        <img :src="previewImage" class="preview-img" alt="预览图" v-if="previewImage">
      </div>
      
      <button class="btn" @click="startSearch">检索甲骨文字</button>
    </div>
    
    <div class="loading" v-if="loading">
      <div class="spinner"></div>
      <p>正在检索甲骨文字，请稍候...</p>
    </div>
    
    <div class="error" v-if="errorMessage">
      {{ errorMessage }}
    </div>
    
    <div class="no-results" v-if="noResults">
      <i class="fas fa-search" style="font-size: 3rem; margin-bottom: 15px;"></i>
      <p>未找到匹配的甲骨片信息</p>
      <p>请尝试上传更清晰的甲骨文字符图片</p>
    </div>
    
    <div class="results-section" v-if="results.length > 0">
      <h2 class="section-title">检索结果</h2>
      <div class="results-container">
        <div v-for="(result, index) in results" 
             :key="index" 
             class="bone-card">
          <div class="bone-header">甲骨片 {{ result.id }}</div>
          
          <div class="bone-content">
            <div class="bone-image-container" ref="boneImageContainer">
              <img :src="getBoneImageUrl(result.id)" 
                   class="bone-image" 
                   :alt="`甲骨片 ${result.id}`"
                   @load="() => handleBoneImageLoad(index)"
                   ref="boneImages">
            </div>
            
            <div class="inscriptions">
              <div class="inscription-title">释文与字形对照</div>
              
              <template v-if="result.data.annotate">
                <div v-for="([sentenceKey, sentenceData], sIndex) in Object.entries(result.data.annotate)" 
                     :key="sIndex"
                     class="sentence">
                  <div v-if="Array.isArray(sentenceData) && sentenceData.length >= 2" 
                       class="sentence-grid">
                    <div v-for="(glyphInfo, gIndex) in sentenceData[1]" 
                         :key="gIndex"
                         class="glyph-pair"
                         :class="{ matched: isGlyphMatched(result.data.hit, sentenceKey, gIndex) }"
                         @click="() => highlightGlyph(index, glyphInfo[1])">
                      <div class="glyph-image-container">
                       <img class="glyph-image" 
     :src="glyphImagePlaceholder" 
     :data-src="getGlyphImage(index, result.id, glyphInfo)"
     @load="handleGlyphImageLoad($event, index, result.id, glyphInfo)"
     :alt="getGlyphAltText(sentenceData[0], gIndex)"
     @error="handleGlyphImageError">
                      </div>
                      
                      <div class="glyph-transcription">
                        {{ getGlyphText(sentenceData[0], gIndex) }}
                      </div>
                    </div>
                  </div>
                </div>
              </template>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <div class="footer">
      <p>© {{ currentYear }} 甲骨文数字化研究平台 | 让古代文字焕发新生</p>
    </div>
  </div>
</template>

<script>
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import sha256 from 'crypto-js/sha256';
export default {
  name: 'OracleCharacterSearch',
  setup() {
    // Refs
    const fileInput = ref(null)
    const previewImage = ref(null)
    const dragActive = ref(false)
    const loading = ref(false)
    const noResults = ref(false)
    const results = ref([])
    const errorMessage = ref('')
    const boneImages = ref([])
    const boneImageContainer = ref([])
    const currentImageData = ref(null)
    const glyphImagePlaceholder = '';
    const router = useRouter()
    
    // 用于存储已报告的错误，避免重复报告
    const reportedErrors = new Set();
    
    // Computed
    const currentYear = computed(() => new Date().getFullYear())
    const uploadAreaStyle = computed(() => ({
      backgroundColor: dragActive.value ? '#fcf9f0' : '',
      borderColor: dragActive.value ? '#8B4513' : '#c9a87c'
    }))

    const handleGlyphImageLoad = async (event, boneIndex, boneId, glyphInfo) => {
      try {
        const img = event.target;
        const imageUrl = await getGlyphImage(boneIndex, boneId, glyphInfo);
        img.src = imageUrl;
      } catch (error) {
        if (!reportedErrors.has('glyph-image-load')) {
          console.error('图片加载失败:', error);
          reportedErrors.add('glyph-image-load');
        }
        img.src = '';
      }
    };

    const goToHome = () => {
      router.push('/');
    };

    // Methods
    const triggerFileInput = () => fileInput.value.click()
    
    const handleDragOver = () => { 
      dragActive.value = true 
    }
    
    const handleDragLeave = () => { 
      dragActive.value = false 
    }
    
    const handleDrop = (e) => {
      e.preventDefault()
      dragActive.value = false
      if (e.dataTransfer.files.length) {
        handleFileSelect(e.dataTransfer.files[0])
      }
    }
    
    const handleFileChange = (e) => {
      if (e.target.files.length) {
        handleFileSelect(e.target.files[0])
      }
    }
    
    const handleFileSelect = (file) => {
      if (!file.type.match('image.*')) {
        showError('请上传图片文件 (JPG, PNG)')
        return
      }
      
      const reader = new FileReader()
      reader.onload = (e) => {
        previewImage.value = e.target.result
        currentImageData.value = e.target.result
      }
      reader.readAsDataURL(file)
    }
    
    const showError = (message) => {
      // 如果错误消息已经显示过，不再重复显示
      if (errorMessage.value !== message) {
        errorMessage.value = message
        setTimeout(() => {
          errorMessage.value = ''
        }, 3000)
      }
    }
    
    const startSearch = async () => {
      if (!currentImageData.value) {
        showError('请先上传甲骨文字符图片')
        return
      }
      
      loading.value = true
      noResults.value = false
      errorMessage.value = ''
      results.value = []
      reportedErrors.clear(); // 开始新搜索时清除已报告的错误
      
      try {
        const base64Data = currentImageData.value.split(',')[1]
        const requestData = {
          image_base64: `data:image/png;base64,${base64Data}`,
          image_url: "",
          image_path: ""
        }
        
        const response = await fetch('https://ms-p89j4ssn-100022641385.gw.ap-guangzhou.ti.tencentcs.com/ms-p89j4ssn/api/recognize/glyph-matching-db', {
          method: 'POST',
          headers: {
            'accept': 'application/json',
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(requestData)
        })
        
        if (!response.ok) {
          throw new Error(`API请求失败: ${response.status}`)
        }
        
        const result = await response.json()
        processResults(result)
        
      } catch (error) {
        // 只报告未报告过的错误
        if (!reportedErrors.has('api-error')) {
          console.error('检索失败:', error)
          showError(`检索失败: ${error.message}`)
          reportedErrors.add('api-error')
        }
      } finally {
        loading.value = false
      }
    }
    
    const processResults = (result) => {
      if (!result.data || !result.data.results || !result.data.results.more_infos.data_obimd) {
        noResults.value = true
        return
      }
      
      const dataObimd = result.data.results.more_infos.data_obimd
      const boneIds = Object.keys(dataObimd)
      
      if (boneIds.length === 0) {
        noResults.value = true
        return
      }
      
      const displayBoneIds = boneIds.length > 5 ? boneIds.slice(0, 5) : boneIds
      results.value = displayBoneIds.map(boneId => ({
        id: boneId,
        data: dataObimd[boneId]
      }))
    }
    
    const getBoneImageUrl = (boneId) => {
      if (boneId.startsWith('H')) {
        const rest = boneId.slice(1)
        const match = rest.match(/^(\d+)([A-Za-z]*)$/)
        if (match) {
          const numPart = match[1].padStart(5, '0')
          const letterPart = match[2]
          boneId = `H${numPart}${letterPart}`
        }
      }
      return `https://test-cos.jgwlbq.org.cn/oracleimg/rubbing/${boneId.toLowerCase()}.jpg`
    }
    
    const getGlyphImage = (boneIndex, boneId, glyphInfo) => {
      if (!glyphInfo || !glyphInfo[2]) {
        if (!reportedErrors.has('invalid-glyph-info')) {
          console.error('无效的字形信息:', glyphInfo);
          reportedErrors.add('invalid-glyph-info');
        }
        return Promise.resolve('');
      }
      
      return getImageUrl(glyphInfo[2])
        .then(url => {
          if (!url || !url.startsWith('http')) {
            throw new Error('无效的图片URL');
          }
          return url;
        })
        .catch(error => {
          if (!reportedErrors.has('glyph-image-url')) {
            console.error('获取字形图片URL失败:', error);
            reportedErrors.add('glyph-image-url');
          }
          return '';
        });
    };
    
    const getImageUrl = async (filename) => {
      const folder = await getTargetFolder(filename, 100);
      return `https://aigc-static.jgw.qq.com/${folder}/${filename}`;
    };

    const getTargetFolder = async (filename, nFolders) => {
  try {
    const hash = sha256(filename).toString();
    const hashInt = BigInt('0x' + hash);
    const folderIndex = Number(hashInt % BigInt(nFolders));
    return `${(folderIndex + 1).toString().padStart(4, '0')}`;
  } catch (error) {
    if (!reportedErrors.has('hash-calculation')) {
      console.error('哈希计算错误:', error);
      reportedErrors.add('hash-calculation');
    }
    return '0038';
  }
};
    
    const getGlyphText = (transcription, index) => transcription?.[index] || ' '
    const getGlyphAltText = (transcription, index) => transcription?.[index] || '甲骨字'
    
    const isGlyphMatched = (hit, group, index) => 
      hit?.some(h => h.group === group && h.index === index)
    
    const handleBoneImageLoad = (index) => {
      // No image processing - just use the backend URLs directly
    }
    
    const highlightGlyph = (boneIndex, position) => {
      if (!position || position.length !== 4) {
        if (!reportedErrors.has('invalid-position-data')) {
          console.error('无效的位置数据，需要[x,y,width,height]', position);
          reportedErrors.add('invalid-position-data');
        }
        return
      }

      const container = boneImageContainer.value[boneIndex]
      const boneImg = boneImages.value[boneIndex]
      
      if (!container || !boneImg) {
        if (!reportedErrors.has('container-not-found')) {
          console.error('未找到甲骨片容器或图片元素');
          reportedErrors.add('container-not-found');
        }
        return
      }

      // Clear old highlight boxes
      const existingBoxes = container.querySelectorAll('.highlight-box')
      existingBoxes.forEach(box => box.remove())

      const [x, y, width, height] = position.map(Number)
      const scaleX = boneImg.clientWidth / boneImg.naturalWidth
      const scaleY = boneImg.clientHeight / boneImg.naturalHeight

      // Create highlight box
      const highlightBox = document.createElement('div')
      highlightBox.className = 'highlight-box'
      Object.assign(highlightBox.style, {
        left: `${x * scaleX}px`,
        top: `${y * scaleY}px`,
        width: `${width * scaleX}px`,
        height: `${height * scaleY}px`,
        position: 'absolute',
        border: '3px solid red',
        boxSizing: 'border-box',
        zIndex: '10',
        pointerEvents: 'none'
      })
      
      container.appendChild(highlightBox)
      highlightBox.scrollIntoView({ behavior: 'smooth', block: 'center' })
    }
    
    const handleGlyphImageError = (event) => {
      if (!reportedErrors.has('glyph-image-error')) {
        console.error('图片加载失败:', event);
        reportedErrors.add('glyph-image-error');
      }
    }
    
    return {
      fileInput,
      previewImage,
      dragActive,
      loading,
      noResults,
      results,
      errorMessage,
      currentYear,
      uploadAreaStyle,
      triggerFileInput,
      handleDragOver,
      handleDragLeave,
      handleDrop,
      handleFileChange,
      startSearch,
      getBoneImageUrl,
      getGlyphImage,
      highlightGlyph,
      boneImages,
      boneImageContainer,
      getGlyphText,
      getGlyphAltText,
      isGlyphMatched,
      handleBoneImageLoad,
      handleGlyphImageError,
      glyphImagePlaceholder,
      handleGlyphImageLoad,
      goToHome,
    }
  }
}
</script>
<style scoped>
.home-button {
  position: absolute;
  top: 20px;
  left: 20px;
  background: #8B4513;
  color: white;
  border: none;
  padding: 8px 15px;
  font-size: 0.9rem;
  border-radius: 50px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 2px 5px rgba(139, 69, 19, 0.3);
  display: flex;
  align-items: center;
  gap: 6px;
  transition: all 0.3s ease;
}

.home-button:hover {
  background: #A0522D;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(139, 69, 19, 0.4);
}
.home-button:hover {
  background: #A0522D;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(139, 69, 19, 0.4);
}

.home-button:active {
  transform: translateY(1px);
}

.back-icon {
  font-size: 16px;
}

.back-button:hover .back-icon {
  transform: translateX(-1px);
}

header {
  position: relative; /* 确保按钮定位正确 */
  text-align: center;
  padding: 30px 0;
  margin-bottom: 30px;
  border-bottom: 2px solid #c9a87c;
}
.container {
    max-width: 1200px;
    margin: 0 auto;
}

header {
    text-align: center;
    padding: 30px 0;
    margin-bottom: 30px;
    border-bottom: 2px solid #c9a87c;
}

h1 {
    font-size: 2.5rem;
    color: #8B4513;
    margin-bottom: 10px;
    text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
}

.subtitle {
    font-size: 1.2rem;
    color: #A0522D;
    max-width: 700px;
    margin: 0 auto;
    line-height: 1.6;
}

.upload-section {
    background: white;
    border-radius: 12px;
    padding: 30px;
    box-shadow: 0 8px 25px rgba(139, 69, 19, 0.15);
    margin-bottom: 40px;
    text-align: center;
    transition: all 0.3s ease;
}

.upload-section:hover {
    transform: translateY(-5px);
    box-shadow: 0 12px 30px rgba(139, 69, 19, 0.2);
}

.upload-area {
    border: 3px dashed #c9a87c;
    border-radius: 10px;
    padding: 40px 20px;
    margin: 20px auto;
    cursor: pointer;
    transition: all 0.3s;
    position: relative;
    max-width: 500px;
}

.upload-area:hover {
    background-color: #fcf9f0;
    border-color: #8B4513;
}

.upload-icon {
    font-size: 3.5rem;
    color: #c9a87c;
    margin-bottom: 15px;
}

.upload-text {
    font-size: 1.2rem;
    color: #8B4513;
    margin-bottom: 10px;
}

.upload-hint {
    color: #A0522D;
    font-size: 0.9rem;
}

.file-input {
    display: none;
}

.preview-container {
    margin-top: 25px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.preview-title {
    font-size: 1.1rem;
    color: #8B4513;
    margin-bottom: 12px;
    font-weight: 600;
}

.preview-img {
    max-width: 150px;
    max-height: 150px;
    border: 2px solid #c9a87c;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}

.btn {
    background: #8B4513;
    color: white;
    border: none;
    padding: 12px 30px;
    font-size: 1.1rem;
    border-radius: 50px;
    cursor: pointer;
    margin-top: 20px;
    transition: all 0.3s;
    box-shadow: 0 4px 10px rgba(139, 69, 19, 0.3);
}

.btn:hover {
    background: #A0522D;
    transform: translateY(-3px);
    box-shadow: 0 6px 15px rgba(139, 69, 19, 0.4);
}

.btn:active {
    transform: translateY(1px);
}

.loading {
    text-align: center;
    padding: 40px;
}

.spinner {
    width: 50px;
    height: 50px;
    border: 5px solid rgba(139, 69, 19, 0.2);
    border-top: 5px solid #8B4513;
    border-radius: 50%;
    margin: 0 auto 20px;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

.error {
    color: #e74c3c;
    text-align: center;
    padding: 20px;
    background: #fdeded;
    border-radius: 8px;
    margin: 20px 0;
}

.no-results {
    text-align: center;
    padding: 40px;
    color: #8B4513;
    font-size: 1.2rem;
}

.results-section {
    display: block;
}

.section-title {
    font-size: 1.8rem;
    color: #8B4513;
    margin: 30px 0 20px;
    padding-bottom: 10px;
    border-bottom: 2px solid #c9a87c;
}

.bone-card {
    background: white;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 8px 25px rgba(139, 69, 19, 0.15);
    margin-bottom: 35px;
    transition: all 0.3s;
}

.bone-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 12px 30px rgba(139, 69, 19, 0.25);
}

.bone-header {
    background: #8B4513;
    color: white;
    padding: 15px 25px;
    font-size: 1.4rem;
    font-weight: 600;
}

.bone-content {
    padding: 25px;
    display: flex;
    flex-direction: column;
    gap: 30px;
}

.bone-image-container {
    position: relative;
    border: 1px solid #e0d6c3;
    border-radius: 8px;
    overflow: hidden;
    max-width: 100%;
    margin: 0 auto;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}

.bone-image {
    width: 100%;
    display: block;
}

.highlight-box {
    position: absolute;
    border: 3px solid red;
    box-sizing: border-box;
    z-index: 10;
    pointer-events: none;
}

.inscriptions {
    background: #f9f5eb;
    border-radius: 8px;
    padding: 20px;
}

.inscription-title {
    font-size: 1.3rem;
    color: #8B4513;
    margin-bottom: 20px;
    padding-bottom: 8px;
    border-bottom: 1px solid #d8c9a9;
}

.sentence {
    margin-bottom: 25px;
    border-bottom: 1px dashed #d8c9a9;
    padding-bottom: 20px;
}

.sentence:last-child {
    border-bottom: none;
    margin-bottom: 0;
    padding-bottom: 0;
}

.sentence-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    padding: 15px;
    background: white;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}

.glyph-pair {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    border-radius: 8px;
    padding: 5px;
    transition: all 0.3s ease;
}

.glyph-image-container {
    width: 70px;
    height: 70px;
    border: 2px solid #d8c9a9;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fcf9f0;
    transition: all 0.2s;
    overflow: hidden;
}

.glyph-image {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.glyph-transcription {
    font-size: 1.1rem;
    color: #5a4a30;
    font-weight: 500;
}

.glyph-pair.matched .glyph-image-container {
    border: 3px solid #e74c3c;
    box-shadow: 0 4px 10px rgba(231, 76, 60, 0.3);
}

.glyph-pair.matched {
    transform: scale(1.08);
}

.glyph-pair:not(.matched):hover {
    transform: scale(1.05);
    background-color: #fdfaf2;
}

.glyph-image-container.placeholder {
    font-size: 2rem;
    color: #b0a08a;
    background: repeating-linear-gradient(
        45deg,
        #f0e6d6,
        #f0e6d6 10px,
        #e8dfd0 10px,
        #e8dfd0 20px
    );
}

.footer {
    text-align: center;
    padding: 30px 0;
    color: #8B4513;
    font-size: 0.9rem;
    border-top: 1px solid #d8c9a9;
    margin-top: 40px;
}

@media (max-width: 768px) {
    h1 {
        font-size: 2rem;
    }
    .subtitle {
        font-size: 1rem;
    }
    .glyph-image-container {
        width: 55px;
        height: 55px;
    }
    .glyph-transcription {
        font-size: 1rem;
    }
}
</style>